package deep2jvmdvm;

/**
 * *******************************************************
 * Author: chinadragon
 * Time: 2020/12/29 上午10:51
 * Name:验证活跃线程作为 GC Root
 * Overview:
 * Usage:
 * GC 回收机制与分代回收策略 https://kaiwu.lagou.com/course/courseInfo.htm?courseId=67#/detail/pc?id=1856
 * Java GC日志查看  https://blog.csdn.net/u013613428/article/details/53763925
 * *******************************************************
 * vm 参数：-Xms200m
 */
public class GCRootThread {
    private int _10MB = 10 * 1024 * 1024;
    private byte[] memory = new byte[8 * _10MB];

    public static void main(String[] args) throws Exception {
        System.out.println("开始前内存情况:");
        printMemory();
        AsyncTask at = new AsyncTask(new GCRootThread());
        Thread thread = new Thread(at);
        thread.start();
        System.gc();
        System.out.println("main方法执行完毕，完成GC");
        printMemory();
        thread.join();
        at = null;
        System.gc();
        System.out.println("线程代码执行完毕，完成GC");
        printMemory();
        //vm 参数：-Xms200m
        /*
            开始前内存情况:
            free is 197 M, total is 200 M,
            main方法执行完毕，完成GC
            free is 116 M, total is 200 M,
            线程代码执行完毕，完成GC
            free is 198 M, total is 200 M,


            可以看出：

            程序刚开始时是 197 内存，当调用第一次 GC 时线程并没有执行结束，并且它作为 GC Root，所以它所引用的 80M 内存并不会被 GC 回收掉。
            thread.join() 保证线程结束再调用后续代码，所以当调用第二次 GC 时，线程已经执行完毕并被置为 null，这时线程已经被销毁，所以之前它所引用的 80M 此时会被 GC 回收掉。
         */
    }

    /**
     * 打印出当前JVM剩余空间和总的空间大小
     */
    public static void printMemory() {
        System.out.print("free is " + Runtime.getRuntime().freeMemory()/1024/1024 + " M, ");
        System.out.println("total is " + Runtime.getRuntime().totalMemory()/1024/1024 + " M, ");
    }
    private static class AsyncTask implements Runnable {
        private GCRootThread gcRootThread;
        public AsyncTask(GCRootThread gcRootThread){
            this.gcRootThread = gcRootThread;
        }
        @Override
        public void run() {
            try{
                Thread.sleep(500);
            } catch(Exception e){}
        }
    }
}
